/*+**************************************************************************/
/***                                                                      ***/
/***   This file is distributed under a BSD license.                      ***/
/***   See LICENSE.txt for details.                                       ***/
/***                                                                      ***/
/**************************************************************************+*/

material tADFMat
{
  vs
  {
    asc vs_3_0                 // hlsl code
    {      
      cbuffer tADFMatVSPara : register(c0) : slot vs 0
      { 
        row_major float4x4 mvp;     
      };

      use tADFMatVSPara;
      
      void main
      (
        in float3 in_pos : POSITION,
        in float2 in_uv0 : TEXCOORD0,
        out float4 out_pos : POSITION,
        out float2 out_uv0 : TEXCOORD0
      )
      {
        out_uv0 = in_uv0;
        out_pos = mul(float4(in_pos,1),mvp);
      }      
    }
  }

  ps
  {
    asc ps_4_0
    {
    
      cbuffer tADFMatPSPara : register(c0) : slot ps 0
      { 
        float3 dnx;
        float3 dny;
        float3 px;
        float3 cp; 
        float3 sp;   
        float3 op;
        float3 mp;   
        float4 id;
        float3 d;
        float3 pstep;
      };
      
      use tADFMatPSPara;

      sampler3D s0 : register(s0);  
      
      float getdistance(float3 pos)
      {   
        return 0.01;   
      /*                                                  
        pos=(pos-op)*sp;
	    float3 m=modf(pos,pos);
		pos=pos*id;

        float3 pos1=pos+float3(0   ,0   ,0);
        float3 pos2=pos+float3(id.x,0   ,0);   
        float3 pos3=pos+float3(0   ,id.y,0);   
        float3 pos4=pos+float3(id.x,id.y,0);   
        float3 pos5=pos+float3(0   ,0   ,id.z);
        float3 pos6=pos+float3(id.x,0   ,id.z);
        float3 pos7=pos+float3(0   ,id.y,id.z);
        float3 pos8=pos+float3(id.x,id.y,id.z);
   
        float d1=tex3D(s0,pos1).x;
        float d2=tex3D(s0,pos2).x;
        d1=lerp(d1,d2,m.x);
        
        float d3=tex3D(s0,pos3).x;
        float d4=tex3D(s0,pos4).x;
        d3=lerp(d3,d4,m.x);
        
        float d5=tex3D(s0,pos5).x;
        float d6=tex3D(s0,pos6).x;
        d5=lerp(d5,d6,m.x);
        
        float d7=tex3D(s0,pos7).x;
        float d8=tex3D(s0,pos8).x;                                        
        d7=lerp(d7,d8,m.x);
        
        d1=lerp(d1,d3,m.y);
        d5=lerp(d5,d7,m.y);
        
        d1=lerp(d1,d5,m.z);        		
        
        return d1;
        */
      }

      float3 getnormal(float3 p)
      {
        float3 n;
        float3 p1 = p;
        float3 p2 = p;
        float3 p3 = p;
        float3 p4 = p;
        float3 p5 = p;
        float3 p6 = p;

        p1.x = p1.x - pstep.x;
        p2.x = p2.x + pstep.x;
        p3.y = p3.y - pstep.y;
        p4.y = p4.y + pstep.y;
        p5.z = p5.z - pstep.z;
        p6.z = p6.z + pstep.z;

        float d1 = getdistance(p1);
        float d2 = getdistance(p2);
        float d3 = getdistance(p3);
        float d4 = getdistance(p4);
        float d5 = getdistance(p5);
        float d6 = getdistance(p6);

        n.x = d1 - d2;
        n.y = d3 - d4;
        n.z = d5 - d6;

        n = normalize(n);

        return n;
      }
      
	  bool intersect(inout float min, inout float max, float3 ro, float3 ird, float3 bbmin, float3 bbmax)
	  {	  
	    float near = (bbmin.x-ro.x)*ird.x;
	    float far = (bbmax.x-ro.x)*ird.x;
	    float temp = near;
	    near = (near>far) ? far : near;
	    far = (temp>far) ? temp : far;
	    min = (near>min) ? near : min;
	    max = (far<max) ? far : max;
	    if(min>max) return 0;
	  

	    near = (bbmin.y-ro.y)*ird.y;
	    far = (bbmax.y-ro.y)*ird.y;
	    temp = near;
	    near = (near>far) ? far : near;
	    far = (temp>far) ? temp : far;
	    min = (near>min) ? near : min;
	    max = (far<max) ? far : max;
	    if(min>max) return 0;
	  

	    near = (bbmin.z-ro.z)*ird.z;
	    far = (bbmax.z-ro.z)*ird.z;
  	    temp = near;
	    near = (near>far) ? far : near;
	    far = (temp>far) ? temp : far;
	    min = (near>min) ? near : min;
	    max = (far<max) ? far : max;
	    if(min>max) return 0;	  

	    return 1;	    
	  }
	  
          
          
      void main
      (
        in float2 screenxy : TEXCOORD0,        
        out float4 result : COLOR0
      )
      {      
        int i=0;     
        float3 pos=px+dnx*screenxy.x+dny*screenxy.y;
        float3 ray=normalize(pos-cp);
        bool found=0;        
        float min=0;
        float max=1000;
        /*
        if (intersect(min, max, pos, float3(1.0/ray.x,1.0/ray.y,1.0/ray.z), op+float3(1.0/8192.0,1.0/8192.0,1.0/8192.0), mp-float3(1.0/8192.0,1.0/8192.0,1.0/8192.0)))
        {           
          pos=pos+ray*min;         
	      for (i=0;i<64;i++)        
          {          
            int inbox = pos.x>=op.x && pos.x<=mp.x &&
					    pos.y>=op.y && pos.y<=mp.y &&
					    pos.z>=op.z && pos.z<=mp.z;
					 
	        if (!found && inbox)
		    {        		      
			  float d=0.01;//getdistance(pos);			
			  found=d<=id.w;			  			    
			  pos=pos+ray*d;			  
			  if (found)
			  {		
			    min-=d;
			  }
			  else
			  {
			    min+=d;
			  }
		    }               
          }
        }
          */      
        if (found)
        {          
          float3 normal=getnormal(pos);//(getnormal(pos)+float3(1.0,1.0,1.0))*0.5;
          result = float4(normal.x,normal.y,normal.z,min);
        }
        else
        {
          result=float4(0,0,0,0.0);
        }                   
      }
    }
  }
};



material tADFShadowMat
{
  vs
  {
    asc vs_3_0                 // hlsl code
    {      
      cbuffer tADFShadowMatVSPara : register(c0) : slot vs 0
      { 
        row_major float4x4 mvp;     
      };

      use tADFShadowMatVSPara;
      
      void main
      (
        in float3 in_pos : POSITION,
        in float2 in_uv0 : TEXCOORD0,
        out float4 out_pos : POSITION,
        out float2 out_uv0 : TEXCOORD0
      )
      {
        out_uv0 = in_uv0;
        out_pos = mul(float4(in_pos,1),mvp);
      }      
    }
  }

  ps
  {
    asc ps_4_0
    {
    
      cbuffer tADFShadowMatPSPara : register(c0) : slot ps 0
      { 
        float3 dnx;
        float3 dny;
        float3 px;
        float3 cp;
        float3 sp;   
        float3 op;
        float3 mp;   
        float4 id;
        float3 d;
        float3 pstep;        
        float3 light;
        float4 phongpara; 
        float4 speccolor;
        float4 diffusecolor;
        float4 ambientcolor;        
      };
      
      use tADFShadowMatPSPara;

      sampler3D s0 : register(s0);
      sampler2D s1 : register(s1);
      
	  
      float4 phong(float3 v,  float3 n, float3 l)
      {
        float diffuse;
        float specular;
        float3 vReflection;
        
        // diffuser Lichtanteil (Wert im Bereich 0..1)
        diffuse = n * l;  
        
        if (diffuse < 0.0)
          diffuse = 0.0;
        else if(diffuse > 1.0)
          diffuse = 1.0;

		vReflection = reflect(l,n);
		
        specular = dot(vReflection, v);
        specular = (specular < 0.0f) ? 0.0f : phongpara.x * pow(specular, phongpara.y);
       
        return (diffusecolor*diffuse) +  (specular*speccolor) + ambientcolor;
      }
          
      float getdistance(float3 pos)
      {                                            
        pos=(pos-op)*sp;
	    float3 m=modf(pos,pos);
		pos=pos*id;

        float3 pos1=pos+float3(0   ,0   ,0);
        float3 pos2=pos+float3(id.x,0   ,0);   
        float3 pos3=pos+float3(0   ,id.y,0);   
        float3 pos4=pos+float3(id.x,id.y,0);   
        float3 pos5=pos+float3(0   ,0   ,id.z);
        float3 pos6=pos+float3(id.x,0   ,id.z);
        float3 pos7=pos+float3(0   ,id.y,id.z);
        float3 pos8=pos+float3(id.x,id.y,id.z);
   
        float d1=tex3D(s0,pos1).x;
        float d2=tex3D(s0,pos2).x;
        d1=lerp(d1,d2,m.x);
        
        float d3=tex3D(s0,pos3).x;
        float d4=tex3D(s0,pos4).x;
        d3=lerp(d3,d4,m.x);
        
        float d5=tex3D(s0,pos5).x;
        float d6=tex3D(s0,pos6).x;
        d5=lerp(d5,d6,m.x);
        
        float d7=tex3D(s0,pos7).x;
        float d8=tex3D(s0,pos8).x;                                        
        d7=lerp(d7,d8,m.x);
        
        d1=lerp(d1,d3,m.y);
        d5=lerp(d5,d7,m.y);
        
        d1=lerp(d1,d5,m.z);        		
        
        return d1;
      }
                
	  bool intersect(inout float min, inout float max, float3 ro, float3 ird, float3 bbmin, float3 bbmax)
	  {	  
	    float near = (bbmin.x-ro.x)*ird.x;
	    float far = (bbmax.x-ro.x)*ird.x;
	    float temp = near;
	    near = (near>far) ? far : near;
	    far = (temp>far) ? temp : far;
	    min = (near>min) ? near : min;
	    max = (far<max) ? far : max;
	    if(min>max) return 0;
	  

	    near = (bbmin.y-ro.y)*ird.y;
	    far = (bbmax.y-ro.y)*ird.y;
	    temp = near;
	    near = (near>far) ? far : near;
	    far = (temp>far) ? temp : far;
	    min = (near>min) ? near : min;
	    max = (far<max) ? far : max;
	    if(min>max) return 0;
	  

	    near = (bbmin.z-ro.z)*ird.z;
	    far = (bbmax.z-ro.z)*ird.z;
  	    temp = near;
	    near = (near>far) ? far : near;
	    far = (temp>far) ? temp : far;
	    min = (near>min) ? near : min;
	    max = (far<max) ? far : max;
	    if(min>max) return 0;	  

	    return 1;	    
	  }
          
      void main
      (
        in float2 screenxy : TEXCOORD0,        
        out float4 result : COLOR0
      )
      { 
        float4 nl=tex2D(s1,screenxy);
  	    float3 pos=px+dnx*screenxy.x+dny*screenxy.y;
		float3 ray=normalize(pos-cp);
		pos=ray*nl.w+pos;        
       
        if (nl.w<=0.0f)
        {
          ray=ray*float3(0.5,0.5,0.5)+float3(0.5,0.5,0.5);  
          result = float4(ray.x,ray.y,ray.z,1.0);
        }
        else
        {
          int i;
          bool hit=0;             
          float4 color = phong(ray,float3(nl.x,nl.y,nl.z),(light-pos));
          
          ray=(light-pos);
          ray=normalize(ray);
                   
          float min=0;
          float max=1000;

         // if (intersect(min, max, pos, float3(1.0/ray.x,1.0/ray.y,1.0/ray.z), op+float3(1.0/8192.0,1.0/8192.0,1.0/8192.0), mp-float3(1.0/8192.0,1.0/8192.0,1.0/8192.0)))                    
          {
           // pos=pos+ray*min;
            for (i=0;i<32;i++)
            {
              int inbox = pos.x>=op.x && pos.x<=mp.x &&
			   		      pos.y>=op.y && pos.y<=mp.y &&
					      pos.z>=op.z && pos.z<=mp.z;					    
		      if (inbox && !hit)
		      {
                float dist = 0.0f;//getdistance(pos);                                 
                hit=dist<id.w;
                pos=pos+ray*dist;
              }            
            }
          }
          color=saturate(color);
          if (hit)
            color=color*float4(0.5,0.5,0.5,0.5);//ambientcolor;
          result=color;		 		  
		}
		       

/*                   
        float4 nl=tex2D(s1,screenxy);
        float3 pos=px+dnx*screenxy.x+dny*screenxy.y;
        float3 ray=normalize(pos-cp);
        pos=ray*nl.w+pos;        
        
        if (nl.w<=0.0f)
        {
          result=float4(0,0,0,1.0);
        }
        else
        {
          int i;
          bool hit=0;   
          bool first=1;       
          float4 color = phong(ray,float3(nl.x,nl.y,nl.z),(light-pos));
          
          ray=(pos-light);
          float len=length(ray)*0.95;
          ray=normalize(ray);
          pos=light;
          float min=0;
          float max=1000;

          if (intersect(min, max, pos, float3(1.0/ray.x,1.0/ray.y,1.0/ray.z), op+float3(1.0/8192.0,1.0/8192.0,1.0/8192.0), mp-float3(1.0/8192.0,1.0/8192.0,1.0/8192.0)))                    
          {
            pos=pos+ray*min;
            for (i=0;i<32;i++)
            {
              int inbox = pos.x>=op.x && pos.x<=mp.x &&
			   		      pos.y>=op.y && pos.y<=mp.y &&
					      pos.z>=op.z && pos.z<=mp.z;					    
		      if (inbox && !hit)
		      {
                float dist = getdistance(pos);                
                if (dist<pstep.x/16)// && !first)
                { 
                  
                  hit=min<len;
                  pos=pos+ray*abs(dist);
                  min=min+abs(dist);
                }
                else
                {
                  pos=pos+ray*abs(dist);
                  min=min+abs(dist);
                }
              }            
            }
          }
          color=saturate(color);
          if (hit)
            color=color*float4(0.5,0.5,0.5,0.5);//ambientcolor;
          result=color;
        }                        
*/        
        
      }      
    }
  }
};




